// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

// Generates 64 bits of DRNG output from a 128 bit state
module A_cse_ocs_dpa_aes10c_xorshift128plus(
input logic [127:0]     seed, // Seed value (for reseeding)
input logic             reseed, // Trigger a reseed
input logic             clk,
input logic             reset_n,

output logic [63:0]     random_out // The output value

      );



reg [127:0]       state;
reg [127:0]       next_state;

reg [63:0]        x, a, b, c, y;
reg               reseed_r;

// Some random value generated with openssl
parameter INIT_STATE = 128'hc8e746d4665879c7c4fc7c1679c9a9da;

always_comb begin
   // Normal operation
   x = state[63:0];
   y = state[127:64];
   next_state[63:0] = y;
   a = x ^ {x[40:0], 23'h0};   // a = x ^ (x << 23);
   b = a ^ {17'h0, a[63:17]};  // b = a ^ (a >> 17);
   c = b ^ y ^ {26'h0, y[63:26]};  // c = b ^ y ^ (y >> 26);
   next_state[127:64] = c;
   random_out = c + y;
end

always_ff @(posedge clk or negedge reset_n) begin
   if (~reset_n) begin
      state <= INIT_STATE;
      reseed_r <= 0;
   end
   else begin 
      // Reseed
      if(reseed_r) begin
         state <= seed;
      end
      else state <= next_state;
      // Self clear reseed
      if(reseed_r) reseed_r <= 0;
      else reseed_r <= reseed;
  end
end

endmodule
